from  cocos.sprite import Sprite
from cocos.layer import Layer
import pyglet
from random import randint
import math
from cocos.actions import *
from cocos.euclid import *

class AnimatedSprite(Sprite):
    def __init__(self,
                         img, position = (0, 0),
                         rotation=0,
                         scale=1,
                         opacity=255,
                         color=(255, 255, 255),
                         anchor=None):
        Sprite.__init__(self, img, position, rotation, scale, opacity, color, anchor)

        self._paused = False
        self._range = (0, 1)

        # frame lookup table
        self._frame_lookup = [ range(0, len(self._animation.frames)) ]
        self._current_lookup_index = 0

        self.range = [0, len(self._animation.frames)]

    def _animate(self, dt):
        self._frame_index += 1
        if self._frame_index >= self.range[1]:
            self._frame_index = self.range[0]
            self.dispatch_event('on_animation_end')

        # use frame lookup table
        frame = self._animation.frames[ self._frame_lookup[self._current_lookup_index][self._frame_index]]
        self._set_texture(frame.image.get_texture())

        if frame.duration != None:
            pyglet.clock.schedule_once(self._animate, frame.duration)
        else:
            self.dispatch_event('on_animation_end')

    def set_frame(self, i):
        ''' Seek to the specified frame '''
        self._frame_index = max(self.range[0], min(self.range[1], i))
        frame = self._animation.frames[self._frame_index]

        pyglet.clock.unschedule(self._animate)
        self._animate(0.0)

    def set_loop(self, begin, end):
        ''' Loop between the begin and end frames '''

        self.range = (begin, end)

        if self._frame_index < begin:
            self._frame_index = begin-1

        pyglet.clock.unschedule(self._animate)
        self._animate(0.0)

    def pause(self):
        ''' pause animation playback '''
        if not self._paused:
            frame = self._animation.frames[self._frame_index]
            self._animate(frame.duration)
            pyglet.clock.unschedule(self._animate)
            self._paused = True

    def play(self):
        ''' resume animation playback '''
        if self._paused:
            frame = self._animation.frames[self._frame_index]
            self._animate(frame.duration)
            self._paused = False

    def set_active_lookup(self, index):
        if index >= 0 or index < len(self._frame_lookup):
            self._current_lookup_index = index
            self._frame_index = 0

    def add_lookup(self, list):
        self._frame_lookup.append(list)
        self.set_loop(0, len(list))

class SpriteLayer(Layer):
    is_event_handler = True     #: enable pyglet's events


class Character(object):
    speed = 1
    strength = 1
    garching = 1
    path = []
    current_path_position = 0

    def __init__(self, img):
        self.img = img
        pass

    def draw(self):
        self.sprite.draw()

    def set_pos(self, x, y):
        self.sprite.x = x
        self.sprite.y = y

    def walk():
        pass

    def rotate():
        pass

    def setup_animation(self, num_rows, num_columns):
        base_image = pyglet.image.load('data/'+self.img)
        animation_grid = pyglet.image.ImageGrid(base_image,
               num_rows,
               num_columns)
        image_frames = []
        for i in range(num_rows*num_columns, 0, -1):
            frame = animation_grid[i-1]
            animation_frame = (
                pyglet.image.AnimationFrame(frame,
                    0.0415))
            image_frames.append(animation_frame)

        animation = pyglet.image.Animation(image_frames)
        self.sprite = AnimatedSprite(animation)

        rect = self.sprite.get_rect()
        rect.set_size((10,10))
        return

class Tatu(Character):
    is_event_handler = True     #: enable pyglet's events
    def __init__(self, img, gender):
        self.gender = gender
        self.img = img
        self.copulate_speed = 5
        self.copulating = False
        self.takeGender = {"male": self.doMale,"female": self.doFemale}
        self.son = None
        self.old = False
        self.direction = 90
        pass

    def copulate(self,couple, layer):
        self.sprite.pause()
        self.sprite.stop()
        couple.sprite.pause()
        couple.sprite.stop()
        self.copulating = True
        couple.copulating = True
        self.layer = layer
        self.sprite.visible = False
        couple.sprite.visible = False
        self.garch = Tatu('CHAR_Couple.png', gender = 'male')
        self.garch.setup_animation(24, 1)
        self.garch.set_pos(self.sprite.x, self.sprite.y)
        self.garch.male = self
        self.garch.female = couple
        self.layer.add(self.garch.sprite)
        self.sprite.schedule_interval(self.tatu_factory,self.copulate_speed)
        return self.garch

    def decopulate(self,couple, layer):
        self.copulating = False
        couple.copulating = False
        self.layer = layer
        #~ self.layer.remove(self.garch)
        self.sprite.visible = True
        couple.sprite.visible = True

        if hasattr(self, 'garch'):

            #~ import pdb; pdb.set_trace()
            if self.garch.sprite in [child[1] for child in self.layer.children]:
                self.layer.remove(self.garch.sprite)
                self.set_pos(self.sprite.x + 50,self.sprite.y + 50)
                couple.set_pos(self.sprite.x - 50, self.sprite.y -50)
        self.sprite.unschedule(self.tatu_factory)

    def tatu_factory(self, dt):
        if randint(0,1):
            self.son  = Tatu('TatuBB.png', gender = 'male')
        else:
            self.son  = Tatu('TatuBB.png', gender = 'female')
        self.son.setup_animation(12, 1)
        #~ import pdb; pdb.set_trace()
        self.son.set_pos(self.sprite.x, self.sprite.y)
        self.layer.add(self.son.sprite)
        self.layer.childrens.append(self.son)
        self.layer.tatues.append(self.son)
        pos = self.son_place(self.sprite.x, self.sprite.y)
        self.son.escape(*pos)
        self.son.sprite.schedule_interval(self.son.tatu_grow, 4)


    def tatu_grow(self, dt):
        #switch(self.gender):
         #   'male':
          #      self.img='Tatu_Male.png'
           # 'female':
            #    self.img='Tatu_Female.png'
        if not self.old:
            print 'Grow to ' + self.gender +' son: ', self
            self.takeGender.get(self.gender,self.errhandler)()
            self.old = True



    def doMale(self):
        print 'Tatu_Male'
        self.img='Tatu_Male.png'

    def doFemale(self):
        print 'Tatu_Female'
        self.img='Tatu_Female.png'

    def errhandler ():
        print "The gender has not been recognised"

    def escape(self,x,y):
        self.sprite.play()
        end_post = Point2(x, y)
        start_pos = (self.sprite.x, self.sprite.y)
        delta = end_post - Point2(*start_pos)
        velocity = 1
        time = delta.magnitude()*1/(50.0*velocity)
        if time < 0.5: time = 0.5
        self.sprite.stop()
        move = MoveTo( (x,y), round(time,1) )
        self.sprite.do( move + CallFunc(self.sprite.pause))

    def son_place(self, x,y):
        first = randint(100,200)
        second = randint(100,200)
        if randint(0,1):
            retx = x+ first
        else:
             retx = x - first
        if randint(0,1):
            rety = y+ second
        else:
             rety = y - second
        return (retx,rety)


class Monster(Character):
    LEFT = 1
    RIGHT = 2
    UP = 4
    DOWN = 8

    def __init__(self, img):
        self.img = img

    def initial_position(self, x_range, y_range):
        x = randint(x_range[0], x_range[1])
        y = randint(y_range[0], y_range[1])

        self.set_pos(x, y)

        self.direction = 0
        self.direction += x < 400 and self.LEFT or self.RIGHT
        self.direction += y < 300 and self.UP or self.DOWN
        print self.direction, self.direction & self.LEFT != 0, self.direction & self.RIGHT != 0, self.direction & self.UP != 0, self.direction & self.DOWN != 0

    def brain(self, velocity=4):
        self.sprite.schedule_interval(self.monster_seek, 1)

    def monster_seek(self, dt):
        self.sprite.stop()
        rotation = math.pi * self.sprite.rotation / 180.0
        rotation_x = math.cos(rotation)
        rotation_y = math.sin(rotation)
        self.sprite.velocity = (
            10 * (self.direction & self.LEFT != 0 and 1 or -1),
            10 * (self.direction & self.UP != 0 and 1 or -1)
        )
        #self.sprite.acceleration = (0, 0)#(10 * rotation_x, 10 * rotation_y)
        self.sprite.do(Move())

        #check position
        x, y = self.sprite.position
        if x < -10 or y < -10 or 810 < x or 610 < y:
            self.initial_position([80, 800-80], [80,600-80]) #restart position.

